package org.ufpe.cin.ip.projeto.Negocios;

import java.io.IOException;

import jxl.read.biff.BiffException;
import jxl.write.WriteException;

import org.ufpe.cin.ip.projeto.Dados.BaseClasses.Carta;
import org.ufpe.cin.ip.projeto.Dados.BaseClasses.CommonPlayer;
import org.ufpe.cin.ip.projeto.Dados.BaseClasses.Jogador;
import org.ufpe.cin.ip.projeto.Dados.BaseClasses.Npc;
import org.ufpe.cin.ip.projeto.Dados.Enums.EnumTipoRepositorio;
import org.ufpe.cin.ip.projeto.Dados.Interfaces.Repositorios.IRepositorioCommonPlayer;
import org.ufpe.cin.ip.projeto.Dados.Repositorios.RepositorioCommonPlayersArquivo;
import org.ufpe.cin.ip.projeto.Dados.Repositorios.RepositorioCommonPlayersArray;
import org.ufpe.cin.ip.projeto.Dados.Repositorios.RepositorioCommonPlayersLista;
import org.ufpe.cin.ip.projeto.Exceptions.BadFormatObjectInRepository;
import org.ufpe.cin.ip.projeto.Exceptions.ElementNotExistsException;
import org.ufpe.cin.ip.projeto.Exceptions.InvalidActionException;
import org.ufpe.cin.ip.projeto.Exceptions.InvalidJogadorException;
import org.ufpe.cin.ip.projeto.Exceptions.UnexpectedRepositoryTypeException;
import org.ufpe.cin.ip.projeto.Exceptions.commonPlayerIsNotInRound;
import org.ufpe.cin.ip.projeto.Exceptions.isNotNpcException;

/**
 * DIGITE AQUI!!!
 *  
 * @author phmb3
 */
public class CommonPlayersPartida {

	IRepositorioCommonPlayer repositorio;

	public CommonPlayersPartida(EnumTipoRepositorio enumTipoRepositorio) throws UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, BadFormatObjectInRepository {	
		if(enumTipoRepositorio.equals(EnumTipoRepositorio.arquivo)){
			this.repositorio = new RepositorioCommonPlayersArquivo();
		} else if(enumTipoRepositorio.equals(EnumTipoRepositorio.TAD)){
			this.repositorio = new RepositorioCommonPlayersLista();
		} else if(enumTipoRepositorio.equals(EnumTipoRepositorio.array)){
			this.repositorio = new RepositorioCommonPlayersArray();
		} else {
			throw new UnexpectedRepositoryTypeException();
		}
	}

	public void criarJogadores(String nome, double saldoJogador) throws UnexpectedRepositoryTypeException, WriteException, BiffException, IOException {
		repositorio.inserir(new Jogador(saldoJogador, 0, nome));
		for(int i = 0; i <= 7; i++){
			repositorio.inserir(new Npc(saldoJogador, i));
		}	
	}

	public CommonPlayer[] pegarJogadores() throws UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository{
		CommonPlayer[] jogadores = new CommonPlayer[repositorio.length()]; 
		for (int i = 0; i < repositorio.length(); i++) {
			jogadores[i] = repositorio.procurar(i);
		}
		return jogadores;
	}

	public String getValorCartaMao(int i) throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		String aux = "";
		if(i ==  0 || i == 1){
			aux = getJogadorUsuario().getMao()[i].getValor().getSimbolo();
		}
		return aux;
	}

	public String getNaipeCartaMao(int i) throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		String aux = "";
		if(i ==  0 || i == 1){
			aux = getJogadorUsuario().getMao()[i].getNaipe().name();
		}
		return aux;
	}

	public Jogador getJogadorUsuario() throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository	 {
		Jogador jogador = null;
		for(CommonPlayer aux : pegarJogadores()) {
			if(aux instanceof Jogador){
				jogador = (Jogador) aux;	
			}
		} 
		if (jogador == null) {
			throw new InvalidJogadorException();
		} 
		return jogador;
	}


	public void apostarNpc(double aposta, Npc npc) throws InvalidActionException {
		if(aposta <= npc.getSaldo()){
			npc.apostar(aposta);
		} else throw new InvalidActionException(); 
	}

	public CommonPlayer getJogadorByID(int i) throws UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		return repositorio.procurar(i);
	}

	public void apostarUsuario(double aposta) throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		getJogadorUsuario().apostar(aposta);
	}

	public void raiseUsuario(double raise) throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		getJogadorUsuario().apostar(raise);
		getJogadorUsuario().setHadRaise(true);
	}


	public void desistirUsuario() throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		if(getJogadorUsuario().isInRound()){
			getJogadorUsuario().desistir(true);
		} else throw new InvalidJogadorException();
	}

	public void allIn() throws InvalidJogadorException, UnexpectedRepositoryTypeException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		apostarUsuario(getJogadorUsuario().getSaldo());
		getJogadorUsuario().setInRound(false);
	}

	public double usuarioCall() throws UnexpectedRepositoryTypeException, InvalidJogadorException, BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		double diferenca = 0;
		double maiorPote = 0;
		for(CommonPlayer jogador : pegarJogadores()){
			if(jogador.getPoteDoJogador() > maiorPote){
				maiorPote = jogador.getPoteDoJogador();
			}
		} 
		diferenca = maiorPote - getJogadorUsuario().getPoteDoJogador();
		getJogadorUsuario().apostar(diferenca);
		return diferenca;
	}

	public void setarCarta(Carta carta, int i ,int j) throws BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		CommonPlayer aux = repositorio.procurar(i);
		aux.getMao()[j] = carta;
		repositorio.atualizar(i, aux);
	}

	public boolean isFoldNpc(CommonPlayer player, Carta[] cartas) throws isNotNpcException, commonPlayerIsNotInRound, ElementNotExistsException, BadFormatObjectInRepository, InvalidActionException {
		boolean result = false;
		if (player instanceof Npc) {
			if (player.isInRound()) {
				int aux = ( (Npc) repositorio.procurar(player)).getAcao(cartas);
				if(aux == 1){
					result = true;
				} else if(aux < 1 || aux > 4){
					throw new InvalidActionException();
				}
			} /*else throw new commonPlayerIsNotInRound();*/
		} else {
			throw new isNotNpcException();
		}
		return result;
	}

	public boolean isRaiseNpc(CommonPlayer player) throws commonPlayerIsNotInRound, isNotNpcException, ElementNotExistsException, BadFormatObjectInRepository, InvalidActionException {
		boolean result = false;
		if (player instanceof Npc) {
			if (player.isInRound()) {
				int aux = ( (Npc) repositorio.procurar(player)).getAcao(player.getMao());
				if(aux == 2){
					result = true;
				} else if(aux < 1 || aux > 4){
					throw new InvalidActionException();
				}
			} else throw new commonPlayerIsNotInRound();
		} else {
			throw new isNotNpcException();
		}
		return result;
	}


	public boolean isCallNpc(CommonPlayer player) throws ElementNotExistsException, BadFormatObjectInRepository, commonPlayerIsNotInRound, isNotNpcException, InvalidActionException {
		boolean result = false;
		if (player instanceof Npc) {
			if (player.isInRound()) {
				int aux = ( (Npc) repositorio.procurar(player)).getAcao(player.getMao());
				if(aux == 3){
					result = true;
				} else if(aux < 1 || aux > 4){
					throw new InvalidActionException();
				}
			} else throw new commonPlayerIsNotInRound();
		} else {
			throw new isNotNpcException();
		}
		return result;
	}

	public boolean isAllInNpc(CommonPlayer player) throws isNotNpcException, commonPlayerIsNotInRound, ElementNotExistsException, BadFormatObjectInRepository, InvalidActionException {
		boolean result = false;
		if (player instanceof Npc) {
			if (player.isInRound()) {
				int aux = ( (Npc) repositorio.procurar(player)).getAcao(player.getMao());
				if(aux < 1 || aux > 4){
					result = true;
				} else if(aux == 0){
					throw new InvalidActionException();
				}
			} else throw new commonPlayerIsNotInRound();
		} else {
			throw new isNotNpcException();
		}
		return result;
	}

	public void foldNpc(Npc npc) throws ElementNotExistsException, BadFormatObjectInRepository {
		repositorio.procurar(npc).desistir(true);
	}

	public void raiseNpc(CommonPlayer npc, double ultimaAposta) throws ElementNotExistsException, BadFormatObjectInRepository, InvalidJogadorException, InvalidActionException {
		int range = ( ( (Npc) npc).getPerfil().getRaiseChance() - ((Npc)npc).getPerfil().getCallChance() + 10);
		double apostaRaise = ultimaAposta * range/100;

		apostarNpc(apostaRaise, (Npc) npc);
	}
	
	public void callNpc(double diferencaPotes, Npc npc) throws InvalidJogadorException, InvalidActionException 
	{
		apostarNpc(diferencaPotes, npc);
	}


	public void allInNpc(Npc npc) throws InvalidJogadorException, InvalidActionException  
	{
		apostarNpc(npc.getSaldo(), npc);
	}

	public void removePlayer(CommonPlayer aux) throws BiffException, WriteException, IOException, ElementNotExistsException, BadFormatObjectInRepository {
		for(int i = 0; i < repositorio.length(); i++){
			if(aux.equals(repositorio.procurar(i))){
				repositorio.remover(i);
			}
		}
	}
}



